package org.afs.gescol.core.service.implementations;

import java.util.ArrayList;
import java.util.List;

import org.afs.gescol.core.dao.interfaces.GlobalParamsDao;
import org.afs.gescol.core.dao.interfaces.SchoolClassDao;
import org.afs.gescol.core.dao.interfaces.SubjectManagmentDao;
import org.afs.gescol.core.dao.interfaces.TeacherManagmentDao;
import org.afs.gescol.core.dto.DataCriteria;
import org.afs.gescol.core.dto.classes.FullSchoolClassDto;
import org.afs.gescol.core.dto.subject.FullSubjectDto;
import org.afs.gescol.core.dto.time.HourlyDto;
import org.afs.gescol.core.dto.time.PeriodDto;
import org.afs.gescol.core.dto.time.SchoolHoursDto;
import org.afs.gescol.core.dto.time.YearSplitCriteriaDto;
import org.afs.gescol.core.model.data.SchoolClass;
import org.afs.gescol.core.model.data.SubjectAssignment;
import org.afs.gescol.core.model.data.TeacherAssignment;
import org.afs.gescol.core.model.params.Durations;
import org.afs.gescol.core.model.params.YearSplit;
import org.afs.gescol.core.service.interfaces.GlobalParamsServices;
import org.afs.gescol.core.service.util.MappingConstants;
import org.afs.gescol.core.service.util.MessageKeyUtil;
import org.scub.foundation.framework.base.exception.TechnicalException;
import org.scub.foundation.framework.base.mapping.util.MapperDozerBean;
import org.scub.foundation.framework.base.messagesource.MessageSourceUtil;

/**
 * GlobalParamsServices implementation.
 * @author Kobla GBENYO (kobla.gbenyo@gmail.com)
 */
public class GlobalParamsServicesImpl implements GlobalParamsServices {

    private MessageSourceUtil messageSourceUtil;

    private MapperDozerBean mapperDozerBean;

    private GlobalParamsDao globalParamsDao;

    private SchoolClassDao schoolClassDao;

    private SubjectManagmentDao subjectManagmentDao;

    private TeacherManagmentDao teacherManagmentDao;

    @Override
    public List<FullSchoolClassDto> getSchoolClassFullData(Long cycleId) {
        final List<FullSchoolClassDto> classes = new ArrayList<FullSchoolClassDto>();
        // get school classes by cycle
        final DataCriteria criteria = new DataCriteria();
        criteria.setCycleId(cycleId);
        final List<SchoolClass> scls = schoolClassDao.getSchoolClassByCriteria(criteria);
        if (scls != null) {
            // for each school class, we get its subjects
            for (SchoolClass scl : scls) {
                final List<FullSubjectDto> subjects = new ArrayList<FullSubjectDto>();
                // get subject by class level and series
                criteria.setSubjectId(null);
                criteria.setLevelId(scl.getClassLevel().getId());
                criteria.setSeriesId(scl.getClassSeries().getId());
                final List<SubjectAssignment> subjs = subjectManagmentDao.getSubjectAssignmentByCriteria(criteria);
                if (subjs != null) {
                    // for each subject, get the teachers
                    for (SubjectAssignment subj : subjs) {
                        final List<Long> teachers = new ArrayList<Long>();
                        //get teachers by subject, class level and series
                        criteria.setSubjectId(subj.getAssignedSubject().getId());
                        final List<TeacherAssignment> tchs = teacherManagmentDao.getTeacherAssignmentByCriteria(criteria);
                        if (tchs != null) {
                            for (TeacherAssignment tch : tchs) {
                                teachers.add(tch.getTeacher().getId());
                            }
                        }

                        final FullSubjectDto fullSubject = new FullSubjectDto();
                        fullSubject.setId(subj.getAssignedSubject().getId());
                        fullSubject.setWeeklyHoursVolume(subj.getAssignedSubjectHourlyVolume());
                        fullSubject.setTeachers(teachers);
                        subjects.add(fullSubject);
                    }
                }

                final FullSchoolClassDto fullSchoolClass = new FullSchoolClassDto();
                fullSchoolClass.setId(scl.getId());
                fullSchoolClass.setSubjects(subjects);
                classes.add(fullSchoolClass);
            }
        }
        return classes;
    }

    @Override
    public SchoolHoursDto getSchoolHoursParams(Long cycleId) {
        if (cycleId == null) {
            throw new TechnicalException(messageSourceUtil.get(MessageKeyUtil.ERROR_GETTING_DURATIONS_NULL_CYCLE_ID));
        }
        final Durations durations = globalParamsDao.getDurationsByCycle(cycleId);
        if (durations == null) {
            throw new TechnicalException(messageSourceUtil.get(MessageKeyUtil.ERROR_GETTING_DURATIONS_NOT_FOUND));
        }
        return new SchoolHoursDto(durations.getDayNumber(), durations.getDailyTimeSlotMax(), durations.getDailyTimeTableMax());
    }

    @Override
    public PeriodDto getCurrentperiod(Long cycleId) {
        if (cycleId == null) {
            throw new TechnicalException(messageSourceUtil.get(MessageKeyUtil.ERROR_GETTING_CURRENT_PERIOD_NULL_CYCLE_ID));
        }
        final YearSplitCriteriaDto criteria = new YearSplitCriteriaDto();
        criteria.setCycleId(cycleId);
        criteria.setStatusId(MappingConstants.CURRENT_PERIOD_STATUS_ID);
        final List<YearSplit> periods = globalParamsDao.getYearSplitByCriteria(criteria);
        if (periods == null || periods.isEmpty()) {
            throw new TechnicalException(messageSourceUtil.get(MessageKeyUtil.ERROR_GETTING_CURRENT_PERIOD_NOT_FOUND));
        }
        return mapperDozerBean.map(periods.get(0), PeriodDto.class);
    }

    @Override
    public List<HourlyDto> getHourly(Long cycleId) {
        return mapperDozerBean.mapList(globalParamsDao.getHourlyTime(cycleId), HourlyDto.class);
    }

    /**
     * Set the value of globalParamsDao.
     * @param globalParamsDao the globalParamsDao to set
     */
    public void setGlobalParamsDao(GlobalParamsDao globalParamsDao) {
        this.globalParamsDao = globalParamsDao;
    }

    /**
     * Set the value of schoolClassDao.
     * @param schoolClassDao the schoolClassDao to set
     */
    public void setSchoolClassDao(SchoolClassDao schoolClassDao) {
        this.schoolClassDao = schoolClassDao;
    }

    /**
     * Set the value of subjectManagmentDao.
     * @param subjectManagmentDao the subjectManagmentDao to set
     */
    public void setSubjectManagmentDao(SubjectManagmentDao subjectManagmentDao) {
        this.subjectManagmentDao = subjectManagmentDao;
    }

    /**
     * Set the value of teacherManagmentDao.
     * @param teacherManagmentDao the teacherManagmentDao to set
     */
    public void setTeacherManagmentDao(TeacherManagmentDao teacherManagmentDao) {
        this.teacherManagmentDao = teacherManagmentDao;
    }

    /**
     * Set the value of mapperDozerBean.
     * @param mapperDozerBean the mapperDozerBean to set
     */
    public void setMapperDozerBean(MapperDozerBean mapperDozerBean) {
        this.mapperDozerBean = mapperDozerBean;
    }

    /**
     * Set the value of messageSourceUtil.
     * @param messageSourceUtil the messageSourceUtil to set
     */
    public void setMessageSourceUtil(MessageSourceUtil messageSourceUtil) {
        this.messageSourceUtil = messageSourceUtil;
    }

}
